/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "dma.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "spi_tftlcd.h"
#include "GUI.h"
#include "key.h"
#include "buzzer.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
buzzer_t buzzer;
char str[32] = {0};
uint16_t adc[33] = {0};
uint16_t adc3[10] = {0};
uint8_t A[6] = {0};
uint8_t D[8] = {0};

uint32_t sysclock_freq = 0;
uint32_t hclk_freq = 0;
uint32_t pclk1_freq = 0;
uint32_t pclk2_freq = 0;

uint8_t adc5_dma_complete = 0;
uint8_t adc3_dma_complete = 0;

// PWM参数变量
uint32_t pwm_frequency = 5000;      // 默认5KHz
uint32_t pwm_duty_cycle = 40;      // 默认40%
uint32_t pulse_count_mode = 1;     // 默认1个脉冲
uint32_t voltage_threshold = 2000; // 默认2.0V (mV)

// Flash相关定义
#define FLASH_USER_START_ADDR   0x08020000  // 用户数据起始地址 (扇区4)
#define FLASH_MAGIC_NUMBER      0x12345678  // 魔数
#define FLASH_SECTOR_4          4           // 扇区4

// PWM参数存储结构体
typedef struct {
    uint32_t magic_number;    // 魔数
    uint32_t frequency;       // 频率
    uint32_t duty_cycle;      // 占空比
    uint32_t pulse_count;     // 脉冲计数
    uint32_t voltage_threshold; // 电压阈值
} PWM_Params_t;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void init_A_D(void);
void read_A_D(uint8_t *A, uint8_t *D);
void display_A_D(uint8_t *A, uint8_t *D);

void pwm_set_dc(TIM_HandleTypeDef *htim, uint32_t channel, uint32_t dc);
void pwm_set_freq(TIM_HandleTypeDef *htim, uint32_t channel, uint32_t freq, uint32_t default_dc);
/* USER CODE END 0 */

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
  

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
	MX_ADC3_Init();
  MX_ADC5_Init();
  MX_I2C1_Init();
  MX_RTC_Init();
  MX_SPI1_Init();
  MX_SPI3_Init();
	MX_TIM1_Init();
  MX_TIM3_Init();      
  MX_TIM15_Init();     
  MX_TIM20_Init();
  // MX_LPUART1_UART_Init();
  MX_USART1_UART_Init();


  /* USER CODE BEGIN 2 */
  // LCD_GPIO_Init();
  Lcd_Init();
  Lcd_Clear(WHITE);

  // // 添加ADC校准
	HAL_StatusTypeDef adc_status;

  // adc_status = HAL_ADCEx_Calibration_Start(&hadc5, ADC_SINGLE_ENDED);
	adc_status = HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED);

  // // 启动ADC DMA
  // adc_status = HAL_ADC_Start_DMA(&hadc5, (uint32_t*)adc, 33);
	adc_status = HAL_ADC_Start_DMA(&hadc3, (uint32_t*)adc3, 10);

  uint32_t tick = HAL_GetTick();
  uint32_t led_tick = tick;

  uint8_t green_led_state = 0;

  // 非阻塞LED相关变量
  static uint8_t blue_led_blinking = 0;
  static uint8_t blue_led_blink_count = 0;
  static uint32_t blue_led_last_tick = 0;
  static uint8_t blue_led_on = 0;

  static uint8_t green_led_blinking = 0;
  static uint32_t green_led_last_tick = 0;
  static uint8_t green_led_on = 0;

  HAL_TIM_Base_Start(&htim1);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  // 设置初始PWM参数
  pwm_set_freq(&htim1, TIM_CHANNEL_1, pwm_frequency, pwm_duty_cycle);

  // 启动TIM3脉冲输出（1Hz）
  TIM3_SetPulseOutput(1);
  TIM3_StartPulseOutput();

  // 启动TIM15输入捕获测量
  TIM15_StartMeasurement();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  // 1. 设备上电后，显示考生手机号
  // 2. 启动方波信号1输出，频率为5KHz，占空比为40%，并将方波信号1频率和占空比显示在屏幕上
  // 3. 按键1可调整频率输出，范围1KHz—10KHz，步进1KHz；按键2可调整占空比输出，范围10%—90%，步进10%
  // 4. 另外输出一路脉冲信号作为测速信号1并显示在LCD上，1s内脉冲数量1、10、100可选，由按键3控制
  // 5. 测量测速信号1并显示，其中测量到100个脉冲信号时，蓝色LED以0.3s的周期闪烁2次然后关闭
  // 6. 可掉电保存方波信号1设置信息，上电后自动读取保存参数并执行输出信号
  // 7. 测量电压输入，其中输入电压超过2.0V时，绿色LED以0.5s的周期闪烁，低于此电压时关闭；并可通过串口读取电压输入电路信息

  // init_A_D();
  while (1)
  {
    /* USER CODE END WHILE */
    unsigned char key = KEY_Scan(0);

    // 设备上电后，显示考生手机号
    Gui_DrawFont_GBK16(16, 0, RED, WHITE, "ID:15139707259");

    // 显示当前PWM参数
    sprintf(str, "F:%dHz,D:%d%%", pwm_frequency, pwm_duty_cycle);
    Gui_DrawFont_GBK16(16, 20, RED, WHITE, (uint8_t*)str);

    // 显示TIM3输出的脉冲计数
    uint32_t output_pulses = TIM3_GetPulseCount();
    sprintf(str, "Out: %lu", output_pulses);
    Gui_DrawFont_GBK16(16, 40, RED, WHITE, (uint8_t*)str);

    // 显示TIM15测量到的脉冲计数
    uint32_t measured_pulses = TIM3_GetPulseCount();
    sprintf(str, "Input: %lu", measured_pulses);
    Gui_DrawFont_GBK16(16, 60, RED, WHITE, (uint8_t*)str);

    // 显示电压输入（取adc3数组的平均值）
    float voltage_sum = 0;
    uint32_t adc_avg = 0;
    for(int i = 0; i < 10; i++) {
        voltage_sum += adc3[i];
    }
    adc_avg = (uint32_t)(voltage_sum / 10);
    float voltage_avg = adc_avg * 3.3 / 4095;
    sprintf(str, "adc_avg: %d Voltage: %.2f", adc_avg, voltage_avg);
    Gui_DrawFont_GBK16(16, 80, RED, WHITE, (uint8_t*)str);

    // 串口输出
    sprintf(str, "Voltage: %.2f\r\n", voltage_avg);
    // HAL_UART_Transmit(&hlpuart1, (uint8_t*)str, strlen(str), 1000);
    HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), 1000);



    // 显示4个按钮的状态
    sprintf(str, "K1:%d K2:%d K3:%d K4:%d", 
            HAL_GPIO_ReadPin(KEY_1_GPIO_Port, KEY_1_Pin),
            HAL_GPIO_ReadPin(KEY_2_GPIO_Port, KEY_2_Pin),
            HAL_GPIO_ReadPin(KEY_3_GPIO_Port, KEY_3_Pin),
            HAL_GPIO_ReadPin(KEY_4_GPIO_Port, KEY_4_Pin));
    Gui_DrawFont_GBK16(16, 100, RED, WHITE, (uint8_t*)str);


    // 绿色LED非阻塞闪烁逻辑
    if(voltage_avg > 2.0)
    {
        green_led_blinking = 1;
    }
    else
    {
        green_led_blinking = 0;
        green_led_on = 0;
        HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET);
    }

    if(green_led_blinking)
    {
        if(HAL_GetTick() - green_led_last_tick >= 500)
        {
            led_green_toggle();
            green_led_on = !green_led_on;
            green_led_last_tick = HAL_GetTick();
        }
    }

    // 蓝色LED非阻塞闪烁逻辑
    if(!blue_led_blinking && measured_pulses >= 100)
    {
        blue_led_blinking = 1;
        blue_led_blink_count = 0;
        blue_led_last_tick = HAL_GetTick();
        blue_led_on = 0;
    }

    if(blue_led_blinking)
    {
        if(HAL_GetTick() - blue_led_last_tick >= 300)
        {
            led_blue_toggle();
            blue_led_on = !blue_led_on;
            blue_led_last_tick = HAL_GetTick();

            if(blue_led_on == 0) // 每次灭灯时计数
            {
                blue_led_blink_count++;
                if(blue_led_blink_count >= 2)
                {
                    blue_led_blinking = 0;
                    TIM15_ResetMeasurement(); // 重置计数
                }
            }
        }
    }

    // 按键处理
    if (key == KEY1_PRES)
    {
        // 调整频率 1KHz-10KHz，步进1KHz
        pwm_frequency += 1000;
        if (pwm_frequency > 10000) {
            pwm_frequency = 1000;
        }
        pwm_set_freq(&htim1, TIM_CHANNEL_1, pwm_frequency, pwm_duty_cycle);
        Gui_DrawFont_GBK16(16, 300, RED, WHITE, (uint8_t*)"KEY1:Freq");
    }
    else if (key == KEY2_PRES)
    {
        // 调整占空比 10%-90%，步进10%
        pwm_duty_cycle += 10;
        if (pwm_duty_cycle > 90) {
            pwm_duty_cycle = 10;
        }
        pwm_set_dc(&htim1, TIM_CHANNEL_1, pwm_duty_cycle);
        Gui_DrawFont_GBK16(16, 300, RED, WHITE, (uint8_t*)"KEY2:Duty");
    }
    else if (key == KEY3_PRES)
    {
        // 调整脉冲计数模式 1、10、100
        if (pulse_count_mode == 1) {
            pulse_count_mode = 10;
        } else if (pulse_count_mode == 10) {
            pulse_count_mode = 100;
        } else {
            pulse_count_mode = 1;
        }
        
        // 重新配置TIM3脉冲输出
        TIM3_SetPulseOutput(pulse_count_mode);
        TIM3_ResetPulseCount();
        TIM15_ResetMeasurement();
        
        Gui_DrawFont_GBK16(16, 300, RED, WHITE, (uint8_t*)"KEY3:Pulse");
    }
    else if (key == KEY4_PRES)
    {
        // 保存设置到Flash
        // save_pwm_settings();
        Gui_DrawFont_GBK16(16, 300, RED, WHITE, (uint8_t*)"KEY4");
    } 
    else if (key == 0)
    {
        Gui_DrawFont_GBK16(16, 300, RED, WHITE, "      ");
    }

    // // LED闪烁
    // if (HAL_GetTick() - led_tick > 500)
    // // {
    //     led_red_toggle();
    //     led_tick = HAL_GetTick();
    // }

		HAL_Delay(10);
  }
  /* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
   */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);

  /** Initializes the RCC Oscillators according to the specified parameters
   * in the RCC_OscInitTypeDef structure.
   */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
  RCC_OscInitStruct.PLL.PLLN = 85;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
   */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

// 将所有相关引脚配置为输入模式
void init_A_D(void){
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 配置为输入模式，无上拉下拉
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;

    // 配置GPIOA相关引脚为输入
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_8 | GPIO_PIN_10;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 配置GPIOB相关引脚为输入
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_10;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 配置GPIOC相关引脚为输入
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void read_A_D(uint8_t *A, uint8_t *D){
  A[0] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
  A[1] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
  A[2] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4);
  A[3] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
  A[4] = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1);
  A[5] = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0);
  
  D[0] = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5);
  D[1] = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4);
  D[2] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_10);
  D[3] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3);
  D[4] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5);
  D[5] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4);
  D[6] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10);
  D[7] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8);
}

void display_A_D(uint8_t *A, uint8_t *D){

     // 使用三目运算符判断A和D数组的值是否大于0，大于0则显示实际值，否则显示0
    Gui_DrawFont_GBK16(16, 80, RED, WHITE, (uint8_t*)(A[0] > 0 ? "A0: 1" : "A0: 0"));
    Gui_DrawFont_GBK16(16, 100, RED, WHITE, (uint8_t*)(A[1] > 0 ? "A1: 1" : "A1: 0"));
    Gui_DrawFont_GBK16(16, 120, RED, WHITE, (uint8_t*)(A[2] > 0 ? "A2: 1" : "A2: 0"));
    Gui_DrawFont_GBK16(16, 140, RED, WHITE, (uint8_t*)(A[3] > 0 ? "A3: 1" : "A3: 0"));
    Gui_DrawFont_GBK16(16, 160, RED, WHITE, (uint8_t*)(A[4] > 0 ? "A4: 1" : "A4: 0"));
    Gui_DrawFont_GBK16(16, 180, RED, WHITE, (uint8_t*)(A[5] > 0 ? "A5: 1" : "A5: 0"));

    Gui_DrawFont_GBK16(100, 20, RED, WHITE, (uint8_t*)(D[0] ? "D0: 1" : "D0: 0"));
    Gui_DrawFont_GBK16(100, 40, RED, WHITE, (uint8_t*)(D[1] ? "D1: 1" : "D1: 0"));
    Gui_DrawFont_GBK16(100, 60, RED, WHITE, (uint8_t*)(D[2] ? "D2: 1" : "D2: 0"));
    Gui_DrawFont_GBK16(100, 80, RED, WHITE, (uint8_t*)(D[3] ? "D3: 1" : "D3: 0"));
    Gui_DrawFont_GBK16(100, 100, RED, WHITE, (uint8_t*)(D[4] ? "D4: 1" : "D4: 0"));
    Gui_DrawFont_GBK16(100, 120, RED, WHITE, (uint8_t*)(D[5] ? "D5: 1" : "D5: 0"));
    Gui_DrawFont_GBK16(100, 140, RED, WHITE, (uint8_t*)(D[6] ? "D6: 1" : "D6: 0"));
    Gui_DrawFont_GBK16(100, 160, RED, WHITE, (uint8_t*)(D[7] ? "D7: 1" : "D7: 0")); 
}



// 设置PWM占空比，允许指定定时器和通道
void pwm_set_dc(TIM_HandleTypeDef *htim, uint32_t channel, uint32_t dc)
{
    uint32_t arr, comp;

    if (dc > 100) dc = 100;

    arr = __HAL_TIM_GET_AUTORELOAD(htim);
    comp = dc * arr / 100;
    __HAL_TIM_SET_COMPARE(htim, channel, comp);
}

// 设置PWM频率，允许指定定时器、通道和默认占空比
void pwm_set_freq(TIM_HandleTypeDef *htim, uint32_t channel, uint32_t freq, uint32_t default_dc)
{
    uint32_t psc, arr, sys;

    if (freq > 0) {
        sys = HAL_RCC_GetSysClockFreq();
        arr = __HAL_TIM_GET_AUTORELOAD(htim);
        psc = (sys / (freq * (arr + 1))) - 1;
        __HAL_TIM_SET_PRESCALER(htim, psc);
        pwm_set_dc(htim, channel, default_dc);
    } else {
        __HAL_TIM_SET_COMPARE(htim, channel, 0);
    }
}

/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
